package edu.isistan.matching;


import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

import org.apache.log4j.PropertyConfigurator;

import edu.isistan.matching.filters.ComposedFilter;
import edu.isistan.matching.filters.GenerateRepresentationFilter;
import edu.isistan.matching.filters.InstantiateMetamodelFilter;
import edu.isistan.matching.filters.StructuralMatchingFilter;
import edu.isistan.matching.filters.io.ComposedParameter;
import edu.isistan.matching.filters.io.MatchingMap;
import edu.isistan.matching.filters.io.XMLMatchingRepresentation;
import edu.isistan.matching.utils.serviceMatching.HybridMatching;

/**
 * Procesador de matching entre dos servicios web
 * @author Mariano
 *
 */
public class MatchProcessor {

	/**
	 * Conjunto de filtros utilizados para obtener el matching entre dos servicios
	 */
	private ComposedFilter<ComposedParameter<String, String>,MatchingMap> matchFilters;
	
	/**
	 * Conjunto de filtros que dado el matching en entre dos servicios genera una entrada formateada del mismo
	 */
	private ComposedFilter<MatchingMap,XMLMatchingRepresentation> formatFilters; 

	/**
	 * Algoritmo de matching a utilizar en el filtro
	 */
	private IMatchingAlgorithm algorithm = null;
	
	/**
	 * Constructor
	 * @param algorithm algoritmo de matching a utilizar
	 */
	public MatchProcessor(IMatchingAlgorithm algorithm) {
		super();
		this.algorithm = algorithm;
		matchFilters = new ComposedFilter<ComposedParameter<String, String>,MatchingMap>();
		matchFilters.addFilter(new InstantiateMetamodelFilter());
		matchFilters.addFilter(new StructuralMatchingFilter(algorithm));
		formatFilters = new ComposedFilter<MatchingMap,XMLMatchingRepresentation>();
		formatFilters.addFilter(new GenerateRepresentationFilter());
	}
	
	/**
	 * Inicializa los filtros 
	 * Esta accion es necesaria antes de la ejecucion de los metodos de matching
	 * @param wsdlSource path a la especificacion wsdl del servicio source
	 * @param wsdlTarget path a la especificacion wsdl del servicio target
	 */
	public void initializeProcess(String wsdlSource,String wsdlTarget) {
		GenerateRepresentationFilter filter = (GenerateRepresentationFilter) formatFilters.getFilter(GenerateRepresentationFilter.class);
		filter.initialize(wsdlSource,wsdlTarget,null,null);
	}
	
	/**
	 * Inicializa los filtros
	 * Esta accion es necesaria antes de la ejecucion de los metodos de matching
	 * @param wsdlSource path a la especificacion wsdl del servicio source
	 * @param wsdlTarget path a la especificacion wsdl del servicio target
	 * @param sourceRef interfaz a la cual hace referencia el servicio source
	 * @param targetRef interfaz a la cual hace referencia el servicio target
	 */
	public void initializeProcess(String wsdlSource,String wsdlTarget,String sourceRef,String targetRef) {
		GenerateRepresentationFilter filter = (GenerateRepresentationFilter) formatFilters.getFilter(GenerateRepresentationFilter.class);
		filter.initialize(wsdlSource,wsdlTarget,sourceRef,targetRef);
	}

	/**
	 * Dados dos archivos wsdl genera una especificacion XML con la mejor
	 * correspondencia de matching
	 * Nota: es necesario ejecutar el metodo initializeProcess() antes de llevar a cabo la ejecucion
	 * 
	 * @param wsdl1Path
	 *            path al archivo wsdl
	 * @param wsdl2Path
	 *            path al archivo wsdl
	 * @return archivo que contiene la representacion XML de la correspondencia
	 */
	public XMLMatchingRepresentation startMatching(String wsdl1Path, String wsdl2Path) {
		ComposedParameter<String, String> in = new ComposedParameter<String, String>(wsdl1Path, wsdl2Path);
		return formatFilters.process(matchFilters.process(in));
	}
	
	/**
	 * Dados dos archivos wsdl obtiene el score con el valor del mejor matching
	 * @param wsdl1Path path al archivo wsdl1
	 * @param wsdl2Path path al archivo wsdl2
	 * @return
	 */
	public double scoreMatching(String wsdl1Path,String wsdl2Path) {
		ComposedParameter<String, String> in = new ComposedParameter<String, String>(wsdl1Path, wsdl2Path);
		return matchFilters.process(in).getScore();
	}

	public IMatchingAlgorithm getAlgorithm() {
		return algorithm;
	}
	
	
	public static void main(String[] args) {
		PropertyConfigurator.configure("log4j.properties");
		MatchProcessor s = new MatchProcessor(new HybridMatching());
		s.initializeProcess("src/experimentos/MortgagePaymentCalculator.java", "src/experimentos/MortgageCalculator.java", "Client", "Server");
		//s.initializeProcess("src/experimentos/Client.java", "src/experimentos/WebService.java", "Client", "Server");
	    XMLMatchingRepresentation xml = s.startMatching("src/experimentos/MortgagePaymentCalculator.java", "src/experimentos/MortgageCalculator.java");
		//XMLMatchingRepresentation xml = s.startMatching("src/experimentos/Client.java","src/experimentos/WebService.java");
		try {
			PrintStream ps = null;
			try {
				ps = new PrintStream(System.out, true, "ISO-8859-1");
			} catch (UnsupportedEncodingException error) {
				System.err.println(error);
				System.exit(-1);
			}
			ps.write(xml.getXml());
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(-1);
		}		
	}
	
}
